﻿//Copyright (c) 2010 Christopher E. S. King (http://chriskingconsulting.com)
//
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files 
// (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, 
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do 
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace King.Linq {

    public partial class KingQueryable {
        public static T Aggregate<T>(this IKingQueryable<T> source, Expression<Func<T, T, T>> func) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source, func);
        }
        public static TAccumulate Aggregate<T, TAccumulate>(this IKingQueryable<T> source, TAccumulate seed, Expression<Func<TAccumulate, T, TAccumulate>> func) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TAccumulate));
            return Invoke<TAccumulate>(method, source, seed, func);
        }
        public static TResult Aggregate<T, TAccumulate, TResult>(this IKingQueryable<T> source, TAccumulate seed, Expression<Func<TAccumulate, T, TAccumulate>> func, Expression<Func<TAccumulate, TResult>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TAccumulate), typeof(TResult));
            return Invoke<TResult>(method, source, seed, func, selector);
        }
        public static bool All<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<bool>(method, source, predicate);
        }
        public static bool Any<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<bool>(method, source);
        }
        public static bool Any<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<bool>(method, source, predicate);
        }
        public static double Average(this IKingQueryable<int> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<double>(method, source);
        }
        public static double? Average(this IKingQueryable<int?> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<double?>(method, source);
        }
        public static double Average(this IKingQueryable<long> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<double>(method, source);
        }
        public static double? Average(this IKingQueryable<long?> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<double?>(method, source);
        }
        public static float Average(this IKingQueryable<float> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<float>(method, source);
        }
        public static float? Average(this IKingQueryable<float?> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<float?>(method, source);
        }
        public static double Average(this IKingQueryable<double> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<double>(method, source);
        }
        public static double? Average(this IKingQueryable<double?> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<double?>(method, source);
        }
        public static decimal Average(this IKingQueryable<decimal> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<decimal>(method, source);
        }
        public static decimal? Average(this IKingQueryable<decimal?> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<decimal?>(method, source);
        }
        public static double Average<T>(this IKingQueryable<T> source, Expression<Func<T, int>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<double>(method, source, selector);
        }
        public static double? Average<T>(this IKingQueryable<T> source, Expression<Func<T, int?>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<double?>(method, source, selector);
        }
        public static float Average<T>(this IKingQueryable<T> source, Expression<Func<T, float>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<float>(method, source, selector);
        }
        public static float? Average<T>(this IKingQueryable<T> source, Expression<Func<T, float?>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<float?>(method, source, selector);
        }
        public static double Average<T>(this IKingQueryable<T> source, Expression<Func<T, long>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<double>(method, source, selector);
        }
        public static double? Average<T>(this IKingQueryable<T> source, Expression<Func<T, long?>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<double?>(method, source, selector);
        }
        public static double Average<T>(this IKingQueryable<T> source, Expression<Func<T, double>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<double>(method, source, selector);
        }
        public static double? Average<T>(this IKingQueryable<T> source, Expression<Func<T, double?>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<double?>(method, source, selector);
        }
        public static decimal Average<T>(this IKingQueryable<T> source, Expression<Func<T, decimal>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<decimal>(method, source, selector);
        }
        public static decimal? Average<T>(this IKingQueryable<T> source, Expression<Func<T, decimal?>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<decimal?>(method, source, selector);
        }
        public static bool Contains<T>(this IKingQueryable<T> source, T item) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<bool>(method, source, item);
        }
        public static bool Contains<T>(this IKingQueryable<T> source, T item, IEqualityComparer<T> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<bool>(method, source, item, comparer);
        }
        public static int Count<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<int>(method, source);
        }
        public static int Count<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<int>(method, source, predicate);
        }
        public static T ElementAt<T>(this IKingQueryable<T> source, int index) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source, index);
        }
        public static T ElementAtOrDefault<T>(this IKingQueryable<T> source, int index) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source, index);
        }
        public static T First<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source);
        }
        public static T First<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source, predicate);
        }
        public static T FirstOrDefault<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source);
        }
        public static T FirstOrDefault<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source, predicate);
        }
        public static T Last<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source);
        }
        public static T Last<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source, predicate);
        }
        public static T LastOrDefault<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source);
        }
        public static T LastOrDefault<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source, predicate);
        }
        public static long LongCount<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<long>(method, source);
        }
        public static long LongCount<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<long>(method, source, predicate);
        }
        public static T Max<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source);
        }
        public static TResult Max<T, TResult>(this IKingQueryable<T> source, Expression<Func<T, TResult>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TResult));
            return Invoke<TResult>(method, source, selector);
        }
        public static T Min<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source);
        }
        public static TResult Min<T, TResult>(this IKingQueryable<T> source, Expression<Func<T, TResult>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TResult));
            return Invoke<TResult>(method, source, selector);
        }
        public static bool SequenceEqual<T>(this IKingQueryable<T> source1, IEnumerable<T> source2) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<bool>(method, source1, source2);
        }
        public static bool SequenceEqual<T>(this IKingQueryable<T> source1, IEnumerable<T> source2, IEqualityComparer<T> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<bool>(method, source1, source2, comparer);
        }
        public static T Single<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source);
        }
        public static T Single<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source, predicate);
        }
        public static T SingleOrDefault<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source);
        }
        public static T SingleOrDefault<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<T>(method, source, predicate);
        }
        public static int Sum(this IKingQueryable<int> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<int>(method, source);
        }
        public static int? Sum(this IKingQueryable<int?> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<int?>(method, source);
        }
        public static long Sum(this IKingQueryable<long> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<long>(method, source);
        }
        public static long? Sum(this IKingQueryable<long?> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<long?>(method, source);
        }
        public static float Sum(this IKingQueryable<float> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<float>(method, source);
        }
        public static float? Sum(this IKingQueryable<float?> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<float?>(method, source);
        }
        public static double Sum(this IKingQueryable<double> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<double>(method, source);
        }
        public static double? Sum(this IKingQueryable<double?> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<double?>(method, source);
        }
        public static decimal Sum(this IKingQueryable<decimal> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<decimal>(method, source);
        }
        public static decimal? Sum(this IKingQueryable<decimal?> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<decimal?>(method, source);
        }
        public static int Sum<T>(this IKingQueryable<T> source, Expression<Func<T, int>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<int>(method, source, selector);
        }
        public static int? Sum<T>(this IKingQueryable<T> source, Expression<Func<T, int?>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<int?>(method, source, selector);
        }
        public static long Sum<T>(this IKingQueryable<T> source, Expression<Func<T, long>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<long>(method, source, selector);
        }
        public static long? Sum<T>(this IKingQueryable<T> source, Expression<Func<T, long?>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<long?>(method, source, selector);
        }
        public static float Sum<T>(this IKingQueryable<T> source, Expression<Func<T, float>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<float>(method, source, selector);
        }
        public static float? Sum<T>(this IKingQueryable<T> source, Expression<Func<T, float?>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<float?>(method, source, selector);
        }
        public static double Sum<T>(this IKingQueryable<T> source, Expression<Func<T, double>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<double>(method, source, selector);
        }
        public static double? Sum<T>(this IKingQueryable<T> source, Expression<Func<T, double?>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<double?>(method, source, selector);
        }
        public static decimal Sum<T>(this IKingQueryable<T> source, Expression<Func<T, decimal>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<decimal>(method, source, selector);
        }
        public static decimal? Sum<T>(this IKingQueryable<T> source, Expression<Func<T, decimal?>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<decimal?>(method, source, selector);
        }
        public static IKingQueryable<TElement> AsQueryable<TElement>(this IEnumerable<TElement> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TElement));
            return Invoke<IKingQueryable<TElement>, TElement>(method, source);
        }
        public static IKingQueryable AsQueryable(this IEnumerable source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod();
            return Invoke<IKingQueryable, object>(method, source);
        }
        public static IKingQueryable<TResult> Cast<TResult>(this IKingQueryable source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source);
        }
        public static IKingQueryable<T> Concat<T>(this IKingQueryable<T> source1, IEnumerable<T> source2) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source1, source2);
        }
        public static IKingQueryable<T> DefaultIfEmpty<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source);
        }
        public static IKingQueryable<T> DefaultIfEmpty<T>(this IKingQueryable<T> source, T defaultValue) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source, defaultValue);
        }
        public static IKingQueryable<T> Distinct<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source);
        }
        public static IKingQueryable<T> Distinct<T>(this IKingQueryable<T> source, IEqualityComparer<T> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source, comparer);
        }
        public static IKingQueryable<T> Except<T>(this IKingQueryable<T> source1, IEnumerable<T> source2) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source1, source2);
        }
        public static IKingQueryable<T> Except<T>(this IKingQueryable<T> source1, IEnumerable<T> source2, IEqualityComparer<T> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source1, source2, comparer);
        }
        public static IKingQueryable<IGrouping<TKey, T>> GroupBy<T, TKey>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey));
            return Invoke<IKingQueryable<IGrouping<TKey, T>>, IGrouping<TKey, T>>(method, source, keySelector);
        }
        public static IKingQueryable<IGrouping<TKey, TElement>> GroupBy<T, TKey, TElement>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector, Expression<Func<T, TElement>> elementSelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey), typeof(TElement));
            return Invoke<IKingQueryable<IGrouping<TKey, TElement>>, IGrouping<TKey, TElement>>(method, source, keySelector, elementSelector);
        }
        public static IKingQueryable<IGrouping<TKey, T>> GroupBy<T, TKey>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector, IEqualityComparer<TKey> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey));
            return Invoke<IKingQueryable<IGrouping<TKey, T>>, IGrouping<TKey, T>>(method, source, keySelector, comparer);
        }
        public static IKingQueryable<IGrouping<TKey, TElement>> GroupBy<T, TKey, TElement>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector, Expression<Func<T, TElement>> elementSelector, IEqualityComparer<TKey> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey), typeof(TElement));
            return Invoke<IKingQueryable<IGrouping<TKey, TElement>>, IGrouping<TKey, TElement>>(method, source, keySelector, elementSelector, comparer);
        }
        public static IKingQueryable<TResult> GroupBy<T, TKey, TElement, TResult>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector, Expression<Func<T, TElement>> elementSelector, Expression<Func<TKey, IEnumerable<TElement>, TResult>> resultSelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey), typeof(TElement), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source, keySelector, elementSelector, resultSelector);
        }
        public static IKingQueryable<TResult> GroupBy<T, TKey, TResult>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector, Expression<Func<TKey, IEnumerable<T>, TResult>> resultSelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source, keySelector, resultSelector);
        }
        public static IKingQueryable<TResult> GroupBy<T, TKey, TResult>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector, Expression<Func<TKey, IEnumerable<T>, TResult>> resultSelector, IEqualityComparer<TKey> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source, keySelector, resultSelector, comparer);
        }
        public static IKingQueryable<TResult> GroupBy<T, TKey, TElement, TResult>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector, Expression<Func<T, TElement>> elementSelector, Expression<Func<TKey, IEnumerable<TElement>, TResult>> resultSelector, IEqualityComparer<TKey> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey), typeof(TElement), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source, keySelector, elementSelector, resultSelector, comparer);
        }
        public static IKingQueryable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IKingQueryable<TOuter> outer, IEnumerable<TInner> inner, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, IEnumerable<TInner>, TResult>> resultSelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TOuter), typeof(TInner), typeof(TKey), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, outer, inner, outerKeySelector, innerKeySelector, resultSelector);
        }
        public static IKingQueryable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IKingQueryable<TOuter> outer, IEnumerable<TInner> inner, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, IEnumerable<TInner>, TResult>> resultSelector, IEqualityComparer<TKey> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TOuter), typeof(TInner), typeof(TKey), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
        }
        public static IKingQueryable<T> Intersect<T>(this IKingQueryable<T> source1, IEnumerable<T> source2) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source1, source2);
        }
        public static IKingQueryable<T> Intersect<T>(this IKingQueryable<T> source1, IEnumerable<T> source2, IEqualityComparer<T> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source1, source2, comparer);
        }
        public static IKingQueryable<TResult> Join<TOuter, TInner, TKey, TResult>(this IKingQueryable<TOuter> outer, IEnumerable<TInner> inner, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, TInner, TResult>> resultSelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TOuter), typeof(TInner), typeof(TKey), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, outer, inner, outerKeySelector, innerKeySelector, resultSelector);
        }
        public static IKingQueryable<TResult> Join<TOuter, TInner, TKey, TResult>(this IKingQueryable<TOuter> outer, IEnumerable<TInner> inner, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, TInner, TResult>> resultSelector, IEqualityComparer<TKey> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TOuter), typeof(TInner), typeof(TKey), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
        }
        public static IKingQueryable<TResult> OfType<TResult>(this IKingQueryable source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source);
        }
        public static IKingOrderedQueryable<T> OrderBy<T, TKey>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey));
            return Invoke<IKingOrderedQueryable<T>, T>(method, source, keySelector);
        }
        public static IKingOrderedQueryable<T> OrderBy<T, TKey>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector, IComparer<TKey> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey));
            return Invoke<IKingOrderedQueryable<T>, T>(method, source, keySelector, comparer);
        }
        public static IKingOrderedQueryable<T> OrderByDescending<T, TKey>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey));
            return Invoke<IKingOrderedQueryable<T>, T>(method, source, keySelector);
        }
        public static IKingOrderedQueryable<T> OrderByDescending<T, TKey>(this IKingQueryable<T> source, Expression<Func<T, TKey>> keySelector, IComparer<TKey> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey));
            return Invoke<IKingOrderedQueryable<T>, T>(method, source, keySelector, comparer);
        }
        public static IKingQueryable<T> Reverse<T>(this IKingQueryable<T> source) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source);
        }
        public static IKingQueryable<TResult> Select<T, TResult>(this IKingQueryable<T> source, Expression<Func<T, TResult>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source, selector);
        }
        public static IKingQueryable<TResult> Select<T, TResult>(this IKingQueryable<T> source, Expression<Func<T, int, TResult>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source, selector);
        }
        public static IKingQueryable<TResult> SelectMany<T, TResult>(this IKingQueryable<T> source, Expression<Func<T, IEnumerable<TResult>>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source, selector);
        }
        public static IKingQueryable<TResult> SelectMany<T, TResult>(this IKingQueryable<T> source, Expression<Func<T, int, IEnumerable<TResult>>> selector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source, selector);
        }
        public static IKingQueryable<TResult> SelectMany<T, TCollection, TResult>(this IKingQueryable<T> source, Expression<Func<T, int, IEnumerable<TCollection>>> collectionSelector, Expression<Func<T, TCollection, TResult>> resultSelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TCollection), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source, collectionSelector, resultSelector);
        }
        public static IKingQueryable<TResult> SelectMany<T, TCollection, TResult>(this IKingQueryable<T> source, Expression<Func<T, IEnumerable<TCollection>>> collectionSelector, Expression<Func<T, TCollection, TResult>> resultSelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TCollection), typeof(TResult));
            return Invoke<IKingQueryable<TResult>, TResult>(method, source, collectionSelector, resultSelector);
        }
        public static IKingQueryable<T> Skip<T>(this IKingQueryable<T> source, int count) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source, count);
        }
        public static IKingQueryable<T> SkipWhile<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source, predicate);
        }
        public static IKingQueryable<T> SkipWhile<T>(this IKingQueryable<T> source, Expression<Func<T, int, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source, predicate);
        }
        public static IKingQueryable<T> Take<T>(this IKingQueryable<T> source, int count) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source, count);
        }
        public static IKingQueryable<T> TakeWhile<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source, predicate);
        }
        public static IKingQueryable<T> TakeWhile<T>(this IKingQueryable<T> source, Expression<Func<T, int, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source, predicate);
        }
        public static IKingOrderedQueryable<T> ThenBy<T, TKey>(this IKingOrderedQueryable<T> source, Expression<Func<T, TKey>> keySelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey));
            return Invoke<IKingOrderedQueryable<T>, T>(method, source, keySelector);
        }
        public static IKingOrderedQueryable<T> ThenBy<T, TKey>(this IKingOrderedQueryable<T> source, Expression<Func<T, TKey>> keySelector, IComparer<TKey> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey));
            return Invoke<IKingOrderedQueryable<T>, T>(method, source, keySelector, comparer);
        }
        public static IKingOrderedQueryable<T> ThenByDescending<T, TKey>(this IKingOrderedQueryable<T> source, Expression<Func<T, TKey>> keySelector) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey));
            return Invoke<IKingOrderedQueryable<T>, T>(method, source, keySelector);
        }
        public static IKingOrderedQueryable<T> ThenByDescending<T, TKey>(this IKingOrderedQueryable<T> source, Expression<Func<T, TKey>> keySelector, IComparer<TKey> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(TKey));
            return Invoke<IKingOrderedQueryable<T>, T>(method, source, keySelector, comparer);
        }
        public static IKingQueryable<T> Union<T>(this IKingQueryable<T> source1, IEnumerable<T> source2) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source1, source2);
        }
        public static IKingQueryable<T> Union<T>(this IKingQueryable<T> source1, IEnumerable<T> source2, IEqualityComparer<T> comparer) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source1, source2, comparer);
        }
        public static IKingQueryable<T> Where<T>(this IKingQueryable<T> source, Expression<Func<T, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source, predicate);
        }
        public static IKingQueryable<T> Where<T>(this IKingQueryable<T> source, Expression<Func<T, int, bool>> predicate) {
            var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(T));
            return Invoke<IKingQueryable<T>, T>(method, source, predicate);
        }
    }
}
